package demo.java.lang.management.jvm;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class XdcsPropertiesParser {

	protected static final Logger logger = LoggerFactory.getLogger(XdcsPropertiesParser.class);

	private static Properties properties = new Properties();
	private static InetAddress inetAddress = null;
    private static final String DEFAULT_LOGDIR = "/var/log";
    private static boolean hasXdcsPropFile = true;
    private static final String DEFAULT_DISTINCT_SERVICE_NUMBER = "1024";
	private static final String DEFAULT_WRITE_QUEUE_SZIE = "4096";


	static {
		InputStream inputStream = XdcsPropertiesParser.class
				.getClassLoader().getResourceAsStream("ximalaya-xdcs.properties");
		if (inputStream == null) {
            logger.error("ximalaya-xdcs.properties not found, let xdcs team know");
            hasXdcsPropFile = false;
		}else {
            try {
                properties.load(inputStream);
            } catch (IOException e) {
                logger.error("ximalaya-xdcs.properties.static,Throwable:", e);
            }finally{
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.error("close inputStream", e);
                }
            }

            try {
                inetAddress = XdcsAddressUtil.getLocalAddress();

                if( inetAddress.getHostAddress().equals("127.0.0.1") ){
                    throw new UnknownHostException("please configure hostname");
                }
            } catch (UnknownHostException e) {
                logger.error("InetAddress.getLocalHost error.", e);
                try {
                    throw new UnknownHostException("please configure hostname");
                } catch (UnknownHostException e1) {
                    logger.error("InetAddress.getLocalHost error.", e1);
                }
            }
        }
	}

	public static Properties getProperties() {
		return properties;
	}

    public static boolean isHasXdcsPropFile() {
        return hasXdcsPropFile;
    }

	public static List<String> getLog4jBlockType() {
		List<String> blockTypeList = new ArrayList<String>();
		try{
			String log4jBlockType = properties.getProperty("xdcs.log4jblock.type");
			if (isEmpty(log4jBlockType)) {
				return blockTypeList;
			}
			String []blockArr = StringUtils.split(log4jBlockType,",");
			if(blockArr != null) {
				for(String blockType:blockArr) {
					blockTypeList.add(blockType);
				}
			}
		}catch (Exception e){
			logger.warn("Xdcs PropertiesParser:getLog4jBlockType error:", e);
		}
		return blockTypeList;
	}

	public static boolean getLog4jBlockSwitch() {
		String log4jBlockSwitch = properties.getProperty("xdcs.log4jblock.switch");
		if (isEmpty(log4jBlockSwitch)) {
			return true;//默认开启 trace  monitor storeMonitor  clientMonitor
		}
		return Boolean.parseBoolean(log4jBlockSwitch);
	}

    public static String getEnvironmentId() {
        String app = System.getProperty("xdcs.environmentId");
        if (isEmpty(app)) {
            return properties.getProperty("xdcs.environmentId");
        }
        return app;

    }

    public static boolean isAutoLogMainstayTimeout() {
        String autolog = properties.getProperty("xdcs.mainstay.timeout.autoLog");
        if (isEmpty(autolog)) {
            return true;
        }
        return Boolean.parseBoolean(autolog);
    }

    public static boolean isTaskAOP() {
        String taskLogString = properties.getProperty("xdcs.taskAOP");
        if (isEmpty(taskLogString)) {
            return false;
        }
        return Boolean.parseBoolean(taskLogString);
    }
    public static boolean isXUID() {
        String xuidString = properties.getProperty("xdcs.xuid");
        if (isEmpty(xuidString)) {
            return false;
        }
        return Boolean.parseBoolean(xuidString);
    }

    public static String getLogDir() {
        String logDir = System.getProperty("xdcs.log.dir");
        if (isEmpty(logDir)) {
            if (isEmpty(properties.getProperty("xdcs.log.dir"))){
                return DEFAULT_LOGDIR;
            }
            return properties.getProperty("xdcs.log.dir");
        }
        return logDir;

    }

    public static String[] getUrlPatterns(){
        String urls = properties.getProperty("xdcs.url.pattern");
        if (StringUtils.isBlank(urls))
            return null;
        return urls.split("\\|");
    }
    public static List<String> getXdcsWhiteList(){
        String whitelists = properties.getProperty("xdcs.span.whitelist");
        if (StringUtils.isBlank(whitelists))
            return null;
        return Arrays.asList(whitelists.split("\\|"));
    }


	public static List<String> getSpanToLogServiceIds(){
		String spanToLogServiceIds = properties.getProperty("xdcs.span.toLog.serviceIds");
		if (StringUtils.isBlank(spanToLogServiceIds))
			return null;
		return Arrays.asList(spanToLogServiceIds.split("\\;"));
	}

    public static int getDistinctMaxServiceNum() {
        String distinctServiceNumber = System.getProperty("xdcs.max.distinct.service");
        if (isEmpty(distinctServiceNumber)) {
            distinctServiceNumber = properties.getProperty("xdcs.max.distinct.service");
            if (isEmpty(distinctServiceNumber)){
                distinctServiceNumber = DEFAULT_DISTINCT_SERVICE_NUMBER;
            }
        }
        return Integer.parseInt(distinctServiceNumber);
    }

	public static String getApp() {
		String app = System.getProperty("xdcs.application.name");
		if (isEmpty(app)) {
			return properties.getProperty("xdcs.application.name");
		}
		if (isEmpty(app)) {
			throw new RuntimeException("xdcs.application.name can not be null");
		}
		return app;

	}
	public static String getMetricSpanTime() {
		String metricSpan = System.getProperty("xdcs.metric.span.duration");
		if (isEmpty(metricSpan)) {
			return properties.getProperty("xdcs.metric.span.duration");
		}
		return metricSpan;

	}
	public static String getEventType() {
		String eventType = System.getProperty("xdcs.application.eventType");
		if (isEmpty(eventType)) {
			return properties.getProperty("xdcs.application.eventType");
		}
		return eventType;

	}
	public static Map<String, String> getLogSizeMapping() {
		String app = System.getProperty("xdcs.log.size");
		if (isEmpty(app)) {
			app= properties.getProperty("xdcs.log.size");
		}
		Map<String, String> urlMap= new HashMap<String, String>();
		if (StringUtils.isNotBlank(app)) {
			String[] urlMappings = app.split("\\;");
			if (urlMappings.length >0) {
				for (String string : urlMappings) {
					String[] pair = string.split("\\:");
					if (pair.length==2) {
						urlMap.put(pair[0], pair[1]);
					}else {
						continue;
					}
				}
			}
		}
		return urlMap;

	}
	public static Map<String, String>getUrlMapping() {
		String app = System.getProperty("xdcs.url.pattern");
		if (isEmpty(app)) {
			app= properties.getProperty("xdcs.url.pattern");
		}
		Map<String, String> urlMap= new HashMap<String, String>();
		if (StringUtils.isNotBlank(app)) {
			String[] urlMappings = app.split("\\;");
			if (urlMappings.length >0) {
				for (String string : urlMappings) {
					String[] pair = string.split("\\:");
					if (pair.length==2) {
						urlMap.put(pair[0], pair[1]);
					}else {
						continue;
					}
				}
			}
		}
		return urlMap;

	}
	public static Map<String, String> getUrlAppNameMapping() {
		String app = System.getProperty("xdcs.url.app.pattern");
		if (isEmpty(app)) {
			app= properties.getProperty("xdcs.url.app.pattern");
		}
		Map<String, String> urlMap= new HashMap<String, String>();
		if (StringUtils.isNotBlank(app)) {
			String[] urlMappings = app.split("\\;");
			if (urlMappings.length >0) {
				for (String string : urlMappings) {
					String[] pair = string.split("\\:");
					if (pair.length==2) {
						urlMap.put(pair[0], pair[1]);
					}else {
						continue;
					}
				}
			}
		}
		return urlMap;

	}
	public static Map<String, String>getPersonalUrlMapping() {
		String app = System.getProperty("xdcs.personal.url.pattern");
		if (isEmpty(app)) {
			app= properties.getProperty("xdcs.personal.url.pattern");
		}
		Map<String, String> urlMap= new HashMap<String, String>();
		if (StringUtils.isNotBlank(app)) {
			String[] urlMappings = app.split("\\;");
			if (urlMappings.length >0) {
				for (String string : urlMappings) {
					String[] pair = string.split("\\:");
					if (pair.length==2) {
						urlMap.put(pair[0], pair[1]);
					}else {
						continue;
					}
				}
			}
		}
		return urlMap;

	}
	public static Map<String, String> getUrlContainMapping() {
		String app = System.getProperty("xdcs.url.contain.pattern");
		if (isEmpty(app)) {
			app= properties.getProperty("xdcs.url.contain.pattern");
		}
		Map<String, String> urlMap= new HashMap<String, String>();
		if (StringUtils.isNotBlank(app)) {
			String[] urlMappings = app.split("\\;");
			if (urlMappings.length >0) {
				for (String string : urlMappings) {
					String[] pair = string.split("\\:");
					if (pair.length==2) {
						urlMap.put(pair[0], pair[1]);
					}else {
						continue;
					}
				}
			}
		}
		return urlMap;

	}

    public static List<String> getUrlExcludeList() {
        String excludeUrl = System.getProperty("xdcs.url.exclude.pattern");
        if (isEmpty(excludeUrl)) {
            excludeUrl= properties.getProperty("xdcs.url.exclude.pattern");
        }
        List<String> urlExcludeList= new ArrayList<String>();
        if (StringUtils.isNotBlank(excludeUrl)) {
            String[] urlMappings = excludeUrl.split("\\;");
            if (urlMappings.length >0) {
                for (String string : urlMappings) {
                    urlExcludeList.add(string);
                }
            }
        }
        return urlExcludeList;
    }

	public static String getLogIdentityAndEventTypeKeys() {
		String excludeLogIdentity = System.getProperty("xdcs.exclude.logIdentityAndEventTypeKeys");
		if (isEmpty(excludeLogIdentity)) {
			excludeLogIdentity= properties.getProperty("xdcs.exclude.logIdentityAndEventTypeKeys");
		}

		return excludeLogIdentity;
	}


	public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }
	public static String getHostName() {
		if (inetAddress !=null) {
			return inetAddress.getHostName();
		}
		return null;
	}
	public static String getIp() {
		if (inetAddress !=null) {
			return inetAddress.getHostAddress();
		}
		return null;
	}
	public static boolean getSampleSwitch() {
		try {
			String sample = System.getProperty("xdcs.application.sample");
			if (isEmpty(sample)) {
				if (properties.getProperty("xdcs.application.sample")!=null) {
					return Boolean.parseBoolean(properties.getProperty("xdcs.application.sample"));
				}else {
					return false;
				}
			}else {
				return Boolean.parseBoolean(sample);
			}
		} catch (Exception e) {
			logger.error("XdcsPropertiesParser:getSampleSwitch:", e);
			return false;
		}
	}

	public static boolean getWriteMainstayLog() {
		try {
			String writeMainstayLog = System.getProperty("xdcs.write.mainstayLog");
			if (isEmpty(writeMainstayLog)) {
				if (properties.getProperty("xdcs.write.mainstayLog")!=null) {
					return Boolean.parseBoolean(properties.getProperty("xdcs.write.mainstayLog"));
				}else {
					return true;
				}
			}else {
				return Boolean.parseBoolean(writeMainstayLog);
			}
		} catch (Exception e) {
			logger.warn("XdcsPropertiesParser:getWriteMainstayLog:", e);
			return true;
		}
	}

	public static boolean getSwitch() {
		try {
			if (properties.getProperty("xdcs.switch")!=null) {
				return Boolean.parseBoolean(properties.getProperty("xdcs.switch"));
			}else {
				return true;
			}
		} catch (Exception e) {
			logger.error("XdcsPropertiesParser:getSwitch:", e);
			return true;
		}
	}
	public static boolean getTaskSwitch() {
		try {
			if (properties.getProperty("xdcs.task.switch")!=null) {
				return Boolean.parseBoolean(properties.getProperty("xdcs.task.switch"));
			}else {
				return true;
			}
		} catch (Exception e) {
			logger.error("XdcsPropertiesParser:getTaskSwitch:", e);
			return true;
		}
	}

    /**
     * 采样频率，默认1/20，20个请求采样1个
     * @return
     */
	public static double getSampleFrequency() {
        double DEFAULT_FREQUENCY = (double)1/20;
		try {
			String frequency = System.getProperty("xdcs.sample.frequency");
			if (isEmpty(frequency)) {
				if (properties.getProperty("xdcs.sample.frequency")!=null) {
					return Double.parseDouble(properties.getProperty("xdcs.sample.frequency"));
				}else {
					return DEFAULT_FREQUENCY;
				}
			}else {
                return Double.parseDouble(frequency);
            }
		} catch (Exception e) {
			logger.error("XdcsPropertiesParser:getSampleFrequency:", e);
		}
		return DEFAULT_FREQUENCY;
	}

    /**
     * 采样的基线，qps大于基线时，使用xdcs.sample.frequency采样
     * @return
     */
    public static int getSampleBaseline() {
        int DEFAULT_BASELINE = 10;
        try {
            String frequency = System.getProperty("xdcs.sample.baseline");
            if (isEmpty(frequency)) {
                if (properties.getProperty("xdcs.sample.baseline")!=null) {
                    return Integer.parseInt(properties.getProperty("xdcs.sample.baseline"));
                }else {
                    return DEFAULT_BASELINE;
                }
            }else {
                return Integer.parseInt(frequency);
            }
        } catch (Exception e) {
            logger.error("XdcsPropertiesParser:getSampleBaseline:", e);
        }
        return DEFAULT_BASELINE;
    }

	public static void setProperties(Properties properties) {
		XdcsPropertiesParser.properties = properties;
	}

	public static InetAddress getInetAddress() {
		return inetAddress;
	}
	public static void setInetAddress(InetAddress inetAddress) {
		XdcsPropertiesParser.inetAddress = inetAddress;
	}

	public static int getWriteQueueSize() {
    	int size;
		String writeQueueSize;
		try {
			writeQueueSize = System.getProperty("xdcs.write.queue.size");
			if (isEmpty(writeQueueSize)) {
				writeQueueSize = properties.getProperty("xdcs.write.queue.size");
                if (isEmpty(writeQueueSize)){
					writeQueueSize = DEFAULT_WRITE_QUEUE_SZIE;
                }
            }
		} catch (Exception e) {
			writeQueueSize = DEFAULT_WRITE_QUEUE_SZIE;
		}

		try {
			size = Integer.parseInt(writeQueueSize);
		} catch (Exception e) {
			size = Integer.parseInt(DEFAULT_WRITE_QUEUE_SZIE);
			logger.error("xdcs.write.queue.size config is error!");
		}

		return size;
	}
}
